############################
# 1. Party ideology ranges figure
############################


load('2_party_ideology.RData')

# Load necessary libraries
library(ggplot2)
library(dplyr)
library(tidyr)

# Calculate min and max for each variable by party
national_ideology_summary <- national_ideology %>%
  group_by(party) %>%
  summarise(
    min_ntl_symbolic = min(std_ntl_symbolic, na.rm = TRUE),
    max_ntl_symbolic = max(std_ntl_symbolic, na.rm = TRUE),
    min_ntl_operational = min(std_ntl_operational, na.rm = TRUE),
    max_ntl_operational = max(std_ntl_operational, na.rm = TRUE),
    min_nominate = min(std_nominate, na.rm = TRUE),
    max_nominate = max(std_nominate, na.rm = TRUE)
  )

# Add in the state ideology
state_ideology_range <- state_ideology %>%
  group_by(state, party) %>%
  summarise(
    min = min(std_state_npat, na.rm = TRUE),
    max = max(std_state_npat, na.rm = TRUE),
    count = sum(!is.na(std_state_npat))
  ) %>%
  ungroup()

state_ideology_range <- state_ideology_range[state_ideology_range$count >= 10,]


# Calculate the distance moved (max - min) for each state and party combination
state_ideology_range <- state_ideology_range %>%
  mutate(distance_moved = max - min)

# Function to get the state's min and max values with the median distance moved
get_median_state_min_max <- function(data, party) {
  party_data <- data %>%
    filter(party == party) %>%
    arrange(distance_moved)
  median_index <- ceiling(nrow(party_data) / 2)
  median_state <- party_data[median_index, ]
  return(median_state)
}

# Get the median state for Democrats
state_dems <- state_ideology_range[state_ideology_range$party == 'Democrat',]
democrat_median_state <- get_median_state_min_max(state_dems, "Democrat")

# Get the median state for Republicans
state_reps <- state_ideology_range[state_ideology_range$party == 'Republican',]
republican_median_state <- get_median_state_min_max(state_reps, "Republican")

# Add min and max to the national_ideology_summary dataframe
national_ideology_summary <- national_ideology_summary %>%
  mutate(
    min_state_npat = ifelse(party == "Democrat", democrat_median_state$min, republican_median_state$min),
    max_state_npat = ifelse(party == "Democrat", democrat_median_state$max, republican_median_state$max)
  )

head(national_ideology_summary)

# Reshape the data for plotting
national_ideology_long <- national_ideology_summary %>%
  pivot_longer(
    cols = starts_with("min_") | starts_with("max_"),
    names_to = c(".value", "variable"),
    names_pattern = "(min|max)_(.*)"
  )

# Define colors for the parties
party_colors <- c("Republican" = "red", "Democrat" = "blue")

# Reorder the factor levels for the variable column
national_ideology_long$variable <- factor(national_ideology_long$variable, levels = c("ntl_symbolic", "ntl_operational", "state_npat", "nominate"))

# Create the plot
ggplot(national_ideology_long, aes(x = variable, y = party)) +
  geom_segment(aes(x = variable, xend = variable, y = min, yend = max, color = party), 
               linewidth = 1.5, 
               arrow = arrow(type = "open", angle = 90, length = unit(0.2, "cm"), ends = "both")) +
  theme_minimal() +
  labs(
    title = "Min-to-Max Range of Standardized National Ideology Variables by Party",
    x = "",
    y = "Standard Deviations from Ideological Midpoint (1990 to 2020)"
  ) +
  scale_x_discrete(labels = c("nominate" = "Federal Parties", "state_npat" = "State Parties", "ntl_symbolic" = "Parties-in-Electorate (symbolic)", "ntl_operational" = "Parties-in-Electorate (operational)")) +
  scale_color_manual(values = party_colors) +
  theme(
    axis.text.x = element_text(angle = 0, vjust = 0.5, size = 12),
    axis.text.y = element_text(size = 12),
    axis.title.x = element_text(size = 14),
    axis.title.y = element_text(size = 14),
    plot.title = element_text(size = 16, hjust = 0.5),
    legend.title = element_blank(),
    legend.text = element_text(size = 12),
    panel.spacing = unit(0.05, "lines")  # Reduce space between elements
  ) +
  coord_flip()




